//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.jboss.resteasy.springboot;

import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.Path;
import javax.ws.rs.core.Application;
import javax.ws.rs.ext.Provider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.env.ConfigurableEnvironment;

public class ResteasyEmbeddedServletInitializer implements BeanFactoryPostProcessor {

    private static final String JAXRS_APP_CLASSES_DEFINITION_PROPERTY = "resteasy.jaxrs.app.registration";
    private static final String JAXRS_APP_CLASSES_PROPERTY = "resteasy.jaxrs.app.classes";
    private static final String JAXRS_APP_CLASSES_PROPERTY_LEGACY = "resteasy.jaxrs.app";
    private static final String JAXRS_DEFAULT_PATH = "resteasy.jaxrs.defaultPath";

    private Set<Class<? extends Application>> applications = new HashSet();
    private Set<Class<?>> allResources = new HashSet();
    private Set<Class<?>> providers = new HashSet();

    private static final Logger logger = LoggerFactory.getLogger(ResteasyEmbeddedServletInitializer.class);

    public ResteasyEmbeddedServletInitializer() {
    }

    private void findJaxrsApplications(ConfigurableListableBeanFactory beanFactory) {
        logger.info("Finding JAX-RS Application classes");
        ResteasyEmbeddedServletInitializer.JaxrsAppClassesRegistration registration = this.getJaxrsAppClassesRegistration(beanFactory);
        switch(registration) {
            case AUTO:
                this.findJaxrsApplicationBeans(beanFactory);
                if (this.applications.size() == 0) {
                    this.findJaxrsApplicationProperty(beanFactory);
                }

                if (this.applications.size() == 0) {
                    this.findJaxrsApplicationScanning(beanFactory);
                }
                break;
            case BEANS:
                this.findJaxrsApplicationBeans(beanFactory);
                break;
            case PROPERTY:
                this.findJaxrsApplicationProperty(beanFactory);
                break;
            case SCANNING:
                this.findJaxrsApplicationScanning(beanFactory);
                break;
            default:
                logger.error("JAX-RS application registration method (%s) not known, no application will be registered", registration.name());
        }

        Object[] var3 = this.applications.toArray();
        int var4 = var3.length;

        for(int var5 = 0; var5 < var4; ++var5) {
            Object appClass = var3[var5];
            logger.info("JAX-RS Application class found: {}", ((Class)appClass).getName());
        }

    }

    private ResteasyEmbeddedServletInitializer.JaxrsAppClassesRegistration getJaxrsAppClassesRegistration(ConfigurableListableBeanFactory beanFactory) {
        ConfigurableEnvironment configurableEnvironment = (ConfigurableEnvironment)beanFactory.getBean(ConfigurableEnvironment.class);
        String jaxrsAppClassesRegistration = configurableEnvironment.getProperty("resteasy.jaxrs.app.registration");
        ResteasyEmbeddedServletInitializer.JaxrsAppClassesRegistration registration = ResteasyEmbeddedServletInitializer.JaxrsAppClassesRegistration.AUTO;
        if (jaxrsAppClassesRegistration == null) {
            logger.info("Property {} has not been set, JAX-RS Application classes registration is being set to AUTO", "resteasy.jaxrs.app.registration");
        } else {
            logger.info("Property {} has been set to {}", "resteasy.jaxrs.app.registration", jaxrsAppClassesRegistration);

            try {
                registration = ResteasyEmbeddedServletInitializer.JaxrsAppClassesRegistration.valueOf(jaxrsAppClassesRegistration.toUpperCase());
            } catch (IllegalArgumentException var7) {
                String errorMesage = String.format("Property %s has not been properly set, value %s is invalid. JAX-RS Application classes registration is being set to AUTO.", "resteasy.jaxrs.app.registration", jaxrsAppClassesRegistration);
                logger.error(errorMesage);
                throw new IllegalArgumentException(errorMesage, var7);
            }
        }

        return registration;
    }

    private void findJaxrsApplicationBeans(ConfigurableListableBeanFactory beanFactory) {
        logger.info("Searching for JAX-RS Application Spring beans");
        Map<String, Application> applicationBeans = beanFactory.getBeansOfType(Application.class, true, false);
        if (applicationBeans != null && applicationBeans.size() != 0) {
            Iterator var3 = applicationBeans.values().iterator();

            while(var3.hasNext()) {
                Application application = (Application)var3.next();
                this.applications.add(application.getClass());
            }

        } else {
            logger.info("No JAX-RS Application Spring beans found");
        }
    }

    private void findJaxrsApplicationProperty(ConfigurableListableBeanFactory beanFactory) {
        ConfigurableEnvironment configurableEnvironment = (ConfigurableEnvironment)beanFactory.getBean(ConfigurableEnvironment.class);
        String jaxrsAppsProperty = configurableEnvironment.getProperty("resteasy.jaxrs.app.classes");
        if (jaxrsAppsProperty == null) {
            jaxrsAppsProperty = configurableEnvironment.getProperty("resteasy.jaxrs.app");
            if (jaxrsAppsProperty == null) {
                logger.info("No JAX-RS Application set via property {}", "resteasy.jaxrs.app.classes");
                return;
            }

            logger.warn("Property {} has been set. Notice that this property has been deprecated and will be removed soon. Please replace it by property {}", "resteasy.jaxrs.app", "resteasy.jaxrs.app.classes");
        } else {
            logger.info("Property {} has been set to {}", "resteasy.jaxrs.app.classes", jaxrsAppsProperty);
        }

        String[] jaxrsClassNames = jaxrsAppsProperty.split(",");
        String[] var5 = jaxrsClassNames;
        int var6 = jaxrsClassNames.length;

        for(int var7 = 0; var7 < var6; ++var7) {
            String jaxrsClassName = var5[var7];
            Class jaxrsClass = null;

            try {
                jaxrsClass = Class.forName(jaxrsClassName.trim());
            } catch (ClassNotFoundException var12) {
                String exceptionMessage = String.format("JAX-RS Application class %s has not been found", jaxrsClassName.trim());
                logger.error(exceptionMessage, var12);
                throw new BeansException(exceptionMessage, var12) {
                };
            }

            this.applications.add(jaxrsClass);
        }

    }

    private void findJaxrsApplicationScanning(BeanFactory beanFactory) {
        List<String> packagesToBeScanned = this.getSpringApplicationPackages(beanFactory);
        Set<Class<? extends Application>> applications = JaxrsApplicationScanner.getApplications(packagesToBeScanned);
        if (applications != null && applications.size() != 0) {
            this.applications.addAll(applications);
        }
    }

    private List<String> getSpringApplicationPackages(BeanFactory beanFactory) {
        return AutoConfigurationPackages.get(beanFactory);
    }

    private void findJaxrsResourcesAndProviderClasses(ConfigurableListableBeanFactory beanFactory) {
        logger.debug("Finding JAX-RS resources and providers Spring bean classes");
        String[] resourceBeans = beanFactory.getBeanNamesForAnnotation(Path.class);
        String[] providerBeans = beanFactory.getBeanNamesForAnnotation(Provider.class);
        String[] var4;
        int var5;
        int var6;
        String providerBean;
        if (resourceBeans != null) {
            var4 = resourceBeans;
            var5 = resourceBeans.length;

            for(var6 = 0; var6 < var5; ++var6) {
                providerBean = var4[var6];
                this.allResources.add(beanFactory.getType(providerBean));
            }
        }

        if (providerBeans != null) {
            var4 = providerBeans;
            var5 = providerBeans.length;

            for(var6 = 0; var6 < var5; ++var6) {
                providerBean = var4[var6];
                this.providers.add(beanFactory.getType(providerBean));
            }
        }

        Object[] var8;
        Object providerClass;
        if (logger.isDebugEnabled()) {
            var8 = this.allResources.toArray();
            var5 = var8.length;

            for(var6 = 0; var6 < var5; ++var6) {
                providerClass = var8[var6];
                logger.debug("JAX-RS resource class found: {}", ((Class)providerClass).getName());
            }
        }

        if (logger.isDebugEnabled()) {
            var8 = this.providers.toArray();
            var5 = var8.length;

            for(var6 = 0; var6 < var5; ++var6) {
                providerClass = var8[var6];
                logger.debug("JAX-RS provider class found: {}", ((Class)providerClass).getName());
            }
        }

    }



    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        logger.debug("Post process bean factory has been called");
        this.findJaxrsApplications(beanFactory);
        this.findJaxrsResourcesAndProviderClasses(beanFactory);
        if (this.allResources.size() == 0) {
            logger.warn("No JAX-RS resource Spring beans have been found");
        }

        if (this.applications.size() == 0) {
            this.registerDefaultJaxrsApp(beanFactory);
        } else {
            BeanDefinitionRegistry registry = (BeanDefinitionRegistry)beanFactory;
            Iterator var3 = this.applications.iterator();

            while(var3.hasNext()) {
                Class<? extends Application> applicationClass = (Class)var3.next();
                ApplicationPath path = (ApplicationPath)AnnotationUtils.findAnnotation(applicationClass, ApplicationPath.class);
                if (path == null) {
                    logger.warn("JAX-RS Application class {} has no ApplicationPath annotation, so it will not be registered", applicationClass.getName());
                } else {
                    logger.debug("registering JAX-RS application class " + applicationClass.getName());
                    GenericBeanDefinition applicationServletBean = this.createApplicationServlet(applicationClass, path.value());
                    registry.registerBeanDefinition(applicationClass.getName(), applicationServletBean);
                }
            }

        }
    }



    private void registerDefaultJaxrsApp(ConfigurableListableBeanFactory beanFactory) {
        BeanDefinitionRegistry registry = (BeanDefinitionRegistry)beanFactory;
        ConfigurableEnvironment configurableEnvironment = (ConfigurableEnvironment)beanFactory.getBean(ConfigurableEnvironment.class);
        String path = configurableEnvironment.getProperty("resteasy.jaxrs.defaultPath", "/");
        GenericBeanDefinition applicationServletBean = this.createApplicationServlet(Application.class, path);
        logger.info("No JAX-RS Application classes have been found. A default, one mapped to '{}', will be registered.", path);
        registry.registerBeanDefinition(Application.class.getName(), applicationServletBean);
    }



    private GenericBeanDefinition createApplicationServlet(Class<? extends Application> applicationClass, String path) {
        GenericBeanDefinition applicationServletBean = new GenericBeanDefinition();
        applicationServletBean.setFactoryBeanName("JaxrsApplicationServletBuilder");
        applicationServletBean.setFactoryMethodName("build");
        Set<Class<?>> resources = this.allResources;
        ConstructorArgumentValues values = new ConstructorArgumentValues();
        values.addIndexedArgumentValue(0, applicationClass.getName());
        values.addIndexedArgumentValue(1, path);
        values.addIndexedArgumentValue(2, resources);
        values.addIndexedArgumentValue(3, this.providers);
        applicationServletBean.setConstructorArgumentValues(values);
        applicationServletBean.setAutowireCandidate(false);
        applicationServletBean.setScope("singleton");
        return applicationServletBean;
    }


    private static enum JaxrsAppClassesRegistration {
        BEANS,
        PROPERTY,
        SCANNING,
        AUTO;

        private JaxrsAppClassesRegistration() {
        }
    }
}
